const {src, dest, series, parallel, watch} = require('gulp');

const del = require('del'); // 自动删除指定的文件，是一个promise方法

// 配置开发服务器
const browserSync = require('browser-sync');
const bs = browserSync.create();

const loadPlugins = require('gulp-load-plugins'); // 通过这一个工具加载所有的插件

const plugins = loadPlugins(); // 自动加载所有插件

// const sass = require('gulp-sass'); // sass样式处理插件
// const babel = require('gulp-babel'); // js处理插件
// const swig = require('gulp-swig'); // 模板转换插件
// const imagemin = require('gulp-imagemin'); // 图片处理插件

const data = {
  menus: [
    {
      name: 'Home',
      icon: 'aperture',
      link: 'index.html'
    },
    {
      name: 'Features',
      link: 'features.html'
    },
    {
      name: 'About',
      link: 'about.html'
    },
  ],
  pkg: require('./package.json'),
  date: new Date()
};

// 清除指定目录文件任务
const clean = () => {
  return del(['dist', 'temp'])
}

// 样式处理任务
const style = () => {
  // 处理配置目录下的所有scss文件
  return src('src/assets/styles/*.scss', {
    base: 'src' // 将基础路径下的路径信息原样封装之后输出，保留原始目录结构，保持路径格式一致
  })
  .pipe(plugins.sass({
    outputStyle: 'expanded', // 输出的css中样式的相关格式处理，完全展开
  })) // 输入之后调用sass方法，处理相关样式文件
  .pipe(dest('temp')) // 输出到相应的目录之下
};

// scripts处理任务
const scripts = () => {
  return src('src/assets/scripts/*.js', {
    base: 'src'
  })
  .pipe(plugins.babel({
    presets: ['@babel/env']
  }))
  .pipe(dest('temp'))
}

// 模板html文件处理任务
const page = () => {
  return src('src/*.html', {  // src('src/**/*.html') 子目录的通配符方式
    base: 'src'
  })
  .pipe(plugins.swig({
    data: data
  }))
  .pipe(dest('temp'))
}

// 图片文件处理任务
const image = () => {
  return src('src/assets/images/**', {
    base: 'src'
  })
  .pipe(plugins.imagemin())
  .pipe(dest('dist'))
}

// 字体文件处理任务，同image，用imagemin插件压缩
const fonts = () => {
  return src('src/assets/fonts/**', {
    base: 'src'
  })
  .pipe(plugins.imagemin())
  .pipe(dest('dist'))
}

// 额外的任务，将public目录下的文件也复制到dist目录下
const extra = () => {
  return src('public/**', {
    base: 'public'
  })
  .pipe(dest('dist'))
}

// 定义一个serve任务
// 启动开发服务器
const serve = () => {
  // 监视文件状态，执行相应任务
  watch('src/assets/styles/*.scss', style);
  watch('src/assets/scripts/*.js', scripts);
  watch('src/*.html', page);
  
  watch([
    'src/assets/images/**',
    'src/assets/fonts/**',
    'public/**'
  ], bs.reload);
  
  bs.init({
    notify: false,
    port: 2020,
    // files: 'dist/**',
    server: {
      // baseDir: 'dist', // 将dist目录下的文件作为启动服务器的根目录
      baseDir: ['temp', 'src', 'public'],
      routes: { // 
        '/node_modules': 'node_modules'
      }
    }
  })
}

const useref = () => {
  return src('temp/*.html', {
    base: 'temp'
  })
  .pipe(plugins.useref({
    searchPath: ['temp', '.']
  }))
  // 三种文件类型 html css js，分别做不同的压缩工作
  // 判断文件的类型，做相应的操作
  .pipe(plugins.if(/\.js$/, plugins.uglify())) // js文件执行uglify
  .pipe(plugins.if(/\.css$/, plugins.cleanCss())) // css文件执行clean
  .pipe(plugins.if(/\.html$/, plugins.htmlmin({
    collapseWhitespace: true, // 折叠所有的空白字符
    minifyCSS: true, // 压缩html文件中的css代码块
    minifyJS: true, // 压缩html文件中的js代码块
  }))) // html文件执行htmlmin
  .pipe(dest('dist'))
}

// 同时执行，使用parallel
// 只有src目录下的文件的构建
const compile = parallel(style, scripts, page);

// 完成所有文件的构建
// 先完成clean操作，然后再执行compile和extra...
// 上线之前执行的任务
// const build = series(clean, parallel(compile, image, fonts, extra));
const build = series(
  clean,
  parallel(
    series(compile, useref),
    image,
    fonts,
    extra
  )
)

const develop = series(compile, serve);

module.exports = {
  compile,
  build,
  clean,
  develop,
  useref
}